#include <myOs/io.h>
#include <myOs/interrupt.h>
#include <myOs/assert.h>
#include <myOs/debug.h>
#include <myOs/task.h>

#define PIT_CHAN0_REG 0X40     // 计数器 1
#define PIT_CHAN2_REG 0X42     // 计数器 2
#define PIT_CTRL_REG 0X43      // 控制字

// 时钟中断
#define HZ 100                 // 100 赫兹
#define OSCILLATOR 1193182     // 原始振荡器
#define CLOCK_COUNTER (OSCILLATOR / HZ) // 发生时钟中断的时间间隔, HZ可以变化，但是 CLOCK_COUNTER 不能超过16位
#define JIFFY (1000 / HZ)      // 10 毫秒

// 蜂鸣器
#define SPEAKER_REG 0x61
#define BEEP_HZ 440
#define BEEP_COUNTER (OSCILLATOR / BEEP_HZ)

// 时间片计数器
u32 volatile jiffies = 0;
u32 jiffy = JIFFY;

u32 volatile beeping = 0;

void start_beep()
{
    if(!beeping)
    {
        outb(SPEAKER_REG, inb(SPEAKER_REG) | 0b11);
    }
    beeping = jiffies + 5;
}

void stop_beep()
{
    if (beeping && jiffies > beeping)
    {
        outb(SPEAKER_REG, inb(SPEAKER_REG) & 0xfc);
        beeping = 0;
    }
}

void clock_handler(int vector)
{
    assert(vector == 0x20);
    send_eoi(vector);

    // if(jiffies % 200 == 0)
    // {
    //     start_beep(); // 蜂鸣器响
    // }

    jiffies++;
    // DEBUGK("clock jiffiess %d ..\n", jiffies);

    stop_beep();
}

void pit_init()
{
    // 配置 计数器 0 的时钟
    outb(PIT_CTRL_REG, 0b00110100); // 00 - 0号计数器， 11 - 先读写低字节后读写高字节，010 - 模式2， 0 - 表示二进制计数器
    outb(PIT_CHAN0_REG, CLOCK_COUNTER & 0xff);
    outb(PIT_CHAN0_REG, (CLOCK_COUNTER >> 8) & 0xff);

    // 配置 计数器 2 的蜂鸣片
    outb(PIT_CTRL_REG, 0b10110110); // 10 - 2号计数器， 11 - 先读写低字节后读写高字节，011 - 模式3， 0 - 表示二进制计数器
    outb(PIT_CHAN2_REG, (u8)BEEP_COUNTER);
    outb(PIT_CHAN2_REG, (u8)(BEEP_COUNTER >> 8));
}

void clock_init()
{
    pit_init();
    set_interrupt_handler(IRQ_CLOCK, clock_handler);
    set_interrupt_mask(IRQ_CLOCK, true);
}